/*
 * SvrConfig.cpp
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */

#include "SvrConfig.h"

SvrConfig::SvrConfig()
{
    listen_port = 0;
    loglevel = 0;
    Svr_Id = 0;
    auth_port = 8080;
    svr_max_connect_count = 10000;

    memset(auth_ip,'\0',sizeof(auth_ip));
    memset(configpath,'\0',sizeof(configpath));
    memset(config_file,'\0',sizeof(config_file));

    memset(listen_ip,'\0',sizeof(listen_ip));

    memset(log_path,'\0',sizeof(log_path));
    memset(rootpath,'\0',sizeof(rootpath));
    memset(Svr_Name,'\0',sizeof(Svr_Name));
    memset(listenethname,'\0',sizeof(listenethname));

    memset(pidfilepath,'\0',sizeof(pidfilepath));

    memset(auth_host,'\0',sizeof(auth_host));

    memset(limit_ip,'\0',sizeof(limit_ip));
    memset(svr_key,'\0',sizeof(svr_key));

    memset(str_buf,'\0',sizeof(str_buf));


    svrtype = 0;
	max_channel = 50;
	is_make_m3u8_list = FALSE;
	is_save_clip = true;
	store_clip_days = 7;
	memset(liverootpath,'\0',sizeof(liverootpath));
	memset(streamconfigfile,'\0',sizeof(streamconfigfile));

    init_config_path();
}

SvrConfig::~SvrConfig()
{
  // TODO Auto-generated destructor stub
}
/*
*
*init config file path
*/
void SvrConfig::init_config_path(void)
{
    /*init server config path*/
    char link[FILE_MAX_PATH];
    memset(link,'\0',sizeof(link));
    sprintf(link, "/proc/%d/exe", getpid());
    readlink(link, configpath, sizeof(configpath));
    size_t len = strlen(configpath);
    for(size_t i= len-1;i>0 ; i--)
    {
       if(configpath[i]=='/')
       {
           break;
       }
       else
       {
           configpath[i] = '\0';
       }
    }

    printf("svr config path:%s\n.", configpath);

    strcpy(config_file,configpath);
    strcat(config_file,"svrconfig.xml");

    strcpy(streamconfigfile,configpath);
    strcat(streamconfigfile,"stream.xml");

    /*init config args*/
    gethostname(this->Svr_Name,sizeof(this->Svr_Name));
    strcpy(svr_key,".hifntv_!@l*w*w$_98765_zux12uownbd3p_");
    strcpy(pidfilepath,"/var/run/xServer/xMediaServerd.pid");

    /*init auth server ip address*/
    this->set_authsvr_address();
}

bool SvrConfig::set_authsvr_address()
{
    if(strlen(this->auth_host) == 0)
    {
        return false;
    }

    /*get remote server address*/
    struct hostent * hptr = NULL;
    char   str[32];
    hptr = gethostbyname(this->auth_host);
    if(hptr != NULL)
    {
         switch(hptr->h_addrtype)
         {
             case AF_INET:
             case AF_INET6:
                 /*update ip,if ip is not eque last ip,from host first ip*/
                 memset(str,'\0', sizeof(str));
                 inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str));
                 if(strlen(auth_ip) == 0 || strcmp(auth_ip,str) != 0)
                 {
                     memset(auth_ip,'\0',sizeof(auth_ip));
                     strcpy(auth_ip,str);
                 }
                 break;
             default:
                 printf("unknown address type\n");
                 break;
         }

         return true;
    }
    else
    {
        return false;
    }
}

int SvrConfig::init()
{
    /*read config file*/
    TiXmlDocument configdoc;
    if(!configdoc.LoadFile(config_file))
    {
        return FAILURE;
    }

    TiXmlHandle docHandle(&configdoc);
    TiXmlElement * xElement = NULL;
    const char  * str_ptr = NULL;

    printf("svr config:=========\r\n");

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("listen").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(listen_ip,str_ptr);
            printf("listen ip:%s\r\n",listen_ip);
        }

    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("port").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            listen_port = atoi(str_ptr);
            printf("listen_port: %s\r\n",str_ptr);
        }
    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("rootpath").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(rootpath,str_ptr);
            printf("rootpath: %s\r\n",rootpath);
        }
    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("virtualpath").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(virtualpath,str_ptr);
            printf("virtualpath: %s\r\n",virtualpath);
        }
    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("livepath").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();
		if(str_ptr != NULL)
		{
			strcpy(this->liverootpath,str_ptr);
			printf("liverootpath: %s\r\n",liverootpath);
		}
	}

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("loglevel").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            loglevel = atoi(str_ptr);
            printf("loglevel : %s\r\n",str_ptr);
        }
    }


    xElement =  docHandle.FirstChildElement("server").FirstChildElement("logpath").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(log_path,str_ptr);
            printf("log_path: %s\r\n",log_path);
        }
    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("authip").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(auth_host,str_ptr);
            printf("authhost: %s\r\n",auth_host);
        }
    }

    xElement =  docHandle.FirstChildElement("server").FirstChildElement("authport").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            auth_port = atoi(str_ptr);
            printf("authport : %s\r\n",str_ptr);
        }
    }


    /*key*/
    xElement =  docHandle.FirstChildElement("server").FirstChildElement("key").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            memset(svr_key,'\0',sizeof(svr_key));
            strcpy(this->svr_key,str_ptr);
            printf("key : %s\r\n",svr_key);
        }
    }

    /*limit_ip*/
    xElement =  docHandle.FirstChildElement("server").FirstChildElement("limitip").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            strcpy(this->limit_ip,str_ptr);
            printf("limit_ip : %s\r\n",limit_ip);
        }
    }

    /*pid file*/
	xElement =  docHandle.FirstChildElement("server").FirstChildElement("pid").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();
		if(str_ptr != NULL)
		{
			 memset(pidfilepath,'\0',sizeof(pidfilepath));
			 strcpy(this->pidfilepath,str_ptr);
			 printf("pidfilepath : %s\r\n",pidfilepath);
		}
	}

	xElement =  docHandle.FirstChildElement("server").FirstChildElement("isqiepian").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();

		if(str_ptr != NULL)
		{
			int clip_flag = atoi(str_ptr);
			if(clip_flag < 0)
			{
				this->is_save_clip = false;
			}
			else if(clip_flag >= 1)
			{
				this->is_save_clip = true;
			}

			printf("isqiepian : %s\r\n",str_ptr);
		}
	}

	xElement =  docHandle.FirstChildElement("server").FirstChildElement("qiepiandays").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();

		if(str_ptr != NULL)
		{
			int days = atoi(str_ptr);
			if(days > 0 && days < 15)
			{
				this->store_clip_days = days;
			}

			printf("qiepiandays : %s\r\n",str_ptr);
		}
	}

	/*svrver type*/
	xElement =  docHandle.FirstChildElement("server").FirstChildElement("svrtype").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();
		if(str_ptr != NULL)
		{
			this->svrtype = atoi(str_ptr);
			printf("svrtype : %d\r\n",svrtype);
		}
	}

	/*svrver max_channel*/
	xElement =  docHandle.FirstChildElement("server").FirstChildElement("max_channel").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();
		if(str_ptr != NULL)
		{
			this->max_channel = atoi(str_ptr);
			printf("max_channel : %d\r\n",max_channel);
		}
	}

	/*is_make_m3u8_list*/
	xElement =  docHandle.FirstChildElement("server").FirstChildElement("is_make_m3u8_list").ToElement();
	if(xElement != NULL)
	{
		str_ptr = xElement->GetText();
		if(str_ptr != NULL)
		{
			this->is_make_m3u8_list = atoi(str_ptr);
			printf("is_make_m3u8_list : %d\r\n",is_make_m3u8_list);
		}
	}


    xElement = NULL;
    str_ptr = NULL;
    printf("svr config end ================\r\n");

    /*check live root path*/
	if(strlen(liverootpath) == 0)
	{
		strcpy(this->liverootpath,rootpath);
		strcat(this->liverootpath,"/live");
	}

    /*return save proc pid to file*/
    return SavePid();
}

int SvrConfig::update()
{
    /*read config file*/
    TiXmlDocument configdoc;
    if(!configdoc.LoadFile(config_file))
    {
        return -1;
    }

    TiXmlHandle docHandle(&configdoc);
    TiXmlElement * xElement = NULL;
    const char  * str_ptr = NULL;

    /*loglevel*/
    xElement =  docHandle.FirstChildElement("server").FirstChildElement("loglevel").ToElement();
    if(xElement != NULL)
    {
        str_ptr = xElement->GetText();
        if(str_ptr != NULL)
        {
            loglevel = atoi(str_ptr);
        }
    }

    xElement = NULL;
    str_ptr = NULL;

    return SUCCESS;
}

int SvrConfig::SavePid()
{
	int fd;
	int FILE_MODE = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
	if((fd = open(pidfilepath, O_WRONLY | O_CREAT, FILE_MODE)) < 0)
	{
		 printf("open file error!");
		 return FAILURE;
	}

	/**
	 * require write lock
	 */
	flock lock;
	lock.l_type = F_WRLCK; // F_RDLCK, F_WRLCK, F_UNLCK
	lock.l_start = 0; // type offset, relative to l_whence
	lock.l_whence = SEEK_SET;  // SEEK_SET, SEEK_CUR, SEEK_END
	lock.l_len = 0;
	if(fcntl(fd, F_SETLK, &lock) < 0){
		if(errno == EACCES || errno == EAGAIN){
			printf("deamon is already running!\n");
			return FAILURE;
		}
		else{
			printf("write lock error!\n");
			return FAILURE;
		}
	}

	if(ftruncate(fd, 0) < 0){
		printf("trancate error!\n");
		return FAILURE;
	}

	char buf[11];
	snprintf(buf, sizeof(buf), "%d", getpid());
	if(write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)){
		printf("write pid error!\n");
		return FAILURE;
	}

	int val;
	if((val = fcntl(fd, F_GETFD, 0)) < 0){
		printf("fnctl F_GETFD error!\n");
		return FAILURE;
	}

	val |= FD_CLOEXEC;
	if(fcntl(fd, F_SETFD, val) < 0){
		printf("fcntl F_SETFD error!\n");
		return FAILURE;
	}

	/*lock pid success*/
	return SUCCESS;
}
